#Create a simulator object
set ns [new Simulator]

#Política de roteamento estado de enlace.
if { [string compare [lindex $argv 0] "ls"] == 0} {
	$ns rtproto LS
	puts "Vamos executar o algoritmo de LS"
} else {
	if { [string compare [lindex $argv 0] "dv"] == 0 } {
		$ns rtproto DV
		puts "Vamos executar o algoritmo de DV"
	} else {
		$ns rtproto LS
	}
}

#Declaração da Coloração que serão usadas nos fluxos UDP.
$ns color 1 Blue
$ns color 2 Red

#################### DECLARAÇÃO DE PARAMETROS DA SIMULAÇÃO #################################

# Tempo total de simulação - FIXO
set simulation_time 15.0
# Tempo de queda do enlace - FIXO
set down_time 5.0
# Tempo de recuperação do enlace - VARIAVEL
set up_time [lindex $argv 1]
set open_stream 0.0
set close_stream 14.0

# Intervalo entre envio de pacotes - VARIAVEL
set stream_interval [lindex $argv 2]

puts "simulation time: $simulation_time"
puts "down time: $down_time"
puts "up time: $up_time"
puts "open stream: $open_stream"
puts "close stream: $close_stream"

#Open the nam trace file
set nf1 [open ls_trace_all.nam w]
set nf2 [open ls_trace_queue13.nam w]
set nf3 [open ls_trace_queue12.nam w]

# Trace de todos os pacotes - Metrica 1
$ns namtrace-all $nf1

#Define a 'finish' procedure
proc finish {} {
	global ns nf1
	$ns flush-trace
	#Close the trace file
	close $nf1
	#Execute nam on the trace file
	#exec nam ls_trace_all.nam &
	exit 0
}
#################################CORPO DO PROGRAMA##########################################


######################################TOPOLOGIA###########################################

#Nós
set no1rd1 [$ns node]
set no2rd1 [$ns node]
set rt1 [$ns node]
set no1rd2 [$ns node]
set no2rd2 [$ns node]
set rt2 [$ns node]
set no1rd3 [$ns node]
set no2rd3 [$ns node]
set rt3 [$ns node]

#Arestas da rede 1
$ns duplex-link $no1rd1 $rt1 1Mb 10ms DropTail
$ns duplex-link $no2rd1 $rt1 1Mb 10ms DropTail

#Arestas da rede 2
$ns duplex-link $no1rd2 $rt2 1Mb 10ms DropTail
$ns duplex-link $no2rd2 $rt2 1Mb 10ms DropTail

#Arestas da rede 3
$ns duplex-link $no1rd3 $rt3 1Mb 10ms DropTail
$ns duplex-link $no2rd3 $rt3 1Mb 10ms DropTail

#Aresta de ligação das redes - política da fila justa e estocática
$ns duplex-link $rt1 $rt2 1Mb 10ms SFQ
$ns cost $rt1 $rt2 2
$ns duplex-link $rt1 $rt3 1Mb 10ms SFQ
$ns cost $rt1 $rt3 2
$ns duplex-link $rt2 $rt3 1Mb 10ms SFQ
$ns cost $rt2 $rt3 1
$ns duplex-link-op $rt1 $rt2 queuePos 0.5
$ns duplex-link-op $rt1 $rt3 queuePos 0.5
$ns duplex-link-op $rt2 $rt3 queuePos 0.5

#Rearranjo da topologia
$ns duplex-link-op $no1rd1 $rt1 orient right-up
$ns duplex-link-op $no2rd1 $rt1 orient right      
#ok
$ns duplex-link-op $no1rd2 $rt2 orient down-right
$ns duplex-link-op $no2rd2 $rt2 orient down-left

$ns duplex-link-op $no1rd3 $rt3 orient left-up
$ns duplex-link-op $no2rd3 $rt3 orient left
#ok
$ns duplex-link-op $rt1 $rt2 orient up-left
$ns duplex-link-op $rt1 $rt3 orient right
$ns duplex-link-op $rt2 $rt3 orient down-right

##############################CONTROLE DO FLUXO#################################################

#Cria o agente UDP para o nó 1 da rede 1 para que este possa enviar pacotes.
set udp0 [new Agent/UDP]
$udp0 set class_ 1
$ns attach-agent $no1rd1 $udp0

# Cria uma fonte de tráfego constante e o conecta ao agente UDP e conseguentemente ao nó 1 da rede 1.
set cbr0 [new Application/Traffic/CBR]
$cbr0 set packetSize_ 500
$cbr0 set interval_ $stream_interval #0.010
$cbr0 attach-agent $udp0
#Cria um agente de recepção no nó 1 da rede 3.
set null0 [new Agent/Null]
$ns attach-agent $no1rd3 $null0
#Cria uma "conexão" entre a fonte(nó 1 da rede 1) e o destino(nó 1 da rede 3)
$ns connect $udp0 $null0

#Cria o agente UDP para o nó 2 da rede 1 para que este possa enviar pacotes.
set udp1 [new Agent/UDP]
$udp1 set class_ 2
$ns attach-agent $no2rd1 $udp1

# Cria uma fonte de tráfego constante e o conecta ao agente UDP e conseguentemente ao nó 2 da rede 1.
set cbr1 [new Application/Traffic/CBR]
$cbr1 set packetSize_ $stream_interval #500
$cbr1 set interval_ 0.010
$cbr1 attach-agent $udp1
#Cria um agente de recepção no nó 2 da rede 3.
set null1 [new Agent/Null]
$ns attach-agent $no2rd3 $null1
#Cria uma "conexão" entre a fonte(nó 2 da rede 1) e o destino(nó 2 da rede 3)
$ns connect $udp1 $null1

#################################Eventos###############################################

#Inicia o tráfegfo entre o nó 1 da rede 1 com o nó 3 da rede 3
$ns at $open_stream "$cbr0 start"
$ns at $close_stream "$cbr0 stop"

# @ Wakim - Para simplificar, vamos considerar apenas um fluxo. Já que a professora não especificou o número de fluxos.
# @ Com um fluxo o tracing fica menor
#Inicia o tráfego entre o nó 2 da rede 1 com o nó 2 da rede 3
#$ns at 2.0 "$cbr1 start"
#$ns at 5.0 "$cbr1 stop"

#Gera a queda do enlace que interconecta os roteadores das redes 1 e 3
$ns rtmodel-at $down_time down $rt1 $rt3
$ns rtmodel-at $up_time up $rt1 $rt3

#@Wakim - Acho que simplificar o cálculo das métricas é melhor não modificar o custo do nó...
#Muda o peso do enlace do roteador 1 ao roteador 3 de 5 para 2 após a recuperação do enlace.
#$ns at 5.0 "$ns cost $rt1 $rt3 5"

#Trace do enlace que ser usado como rota alternativa - Metrica 2
$ns namtrace-queue $rt1 $rt2 $nf2
#Trace do enlace que vai cair - Metrica 3
$ns namtrace-queue $rt1 $rt3 $nf3

#Call the finish procedure after 10 seconds simulation time
$ns at $simulation_time "finish"

#Run the simulation
$ns run
